\documentstyle [a4,11pt,twoside]{article}
\textheight 240 mm
\textwidth 160mm
\topmargin -2.5cm
\evensidemargin -0.4cm
\oddsidemargin 1.0cm
\begin{document}

\thispagestyle{empty}
\begin {center}
\hskip2.1cm{\Large Институт физико-технических проблем}\\
\vskip1.6cm
\hskip9.8cm{\Large  Дубна}
\vskip0.1cm
\end{center}
\hspace*{-10mm}\rule{170mm}{0.2mm}
\vskip1.0cm
\hskip11.5cm{\Large 93-9-7}\\
\vskip5.5cm
\hskip1.3cm{\Large O.S. Rasizade}\\
\vskip1.5cm
\begin{center}{\Large {\it Virtual Panels}: Graphics Interface
        for the Laboratory Instrumentation. 1.Basics and Controls}
\end{center}
\vskip9.0cm
\centerline{\Large 1993}

\newpage
\thispagestyle{empty}
\vspace*{6.0cm}
\hspace*{-6.5mm}{\bf \mbox{Rasizade O.S.}}\\
\vskip0.2cm
\hspace*{-6.5mm}{ {\bf {\it Virtual Panels}: Graphics Interface
        for the Laboratory Instrumentation. 1. Basics and Controls.}\\
\vskip0.5cm
\noindent
The C++ object-oriented class library for creating data acquisition and
presentation applications with user-friendly interface is presented. In
this part the basic notions of {\it Virtual Panels} and complete
description of Control classes are given.

\newpage


\small
\section*{1. Overview}

\subsection*{1.1. What is {\it Virtual Panels} ?}

{\it Virtual Panels} helps you to create DOS-oriented Graphics User
Interface for
laboratory instrumentation that makes it easy and quick to write data
acquisition applications which have state-of-the-art look and feeling.
It is an object-oriented library of classes written for Borland C++
compiler with BGI graphics interface. It is designed so that you need
only to declare what do you want to see on the screen and how do you want
to feel it. It has become possible due to the object-oriented features
of C++ language, so you have to be familiar with object-oriented
programming and C++ to use {\it Virtual Panels}.

We chose C++ because it has become most popular and widely used
object-oriented language today. BGI interface had been chosen because it
provided us with all necessary facilities and is a standard de facto in
Russia. Borland C++ optimizing compiler also becomes such a standard
due to its low price, power and convenience of its IDE.

\subsection*{1.2 The idea behind {\it Virtual Panels}}

My main objective was to write universal tool that would avoid once and
for all usually overburdening labor of writing user friendly interface
for laboratory applications. In my interests was to design
{\it Virtual Panels} so
that to make its subsequent use as easy as possible. I inclined towards
the cheap and restricted in resources IBM AT with single task operating
system MS DOS mainly because that is what you find usually in our
laboratories. Therefore {\it Virtual Panels} was designed with
intentions:\\

 * to save memory - for average application you add only about 30K -
 50K bytes to your program linking {\it Virtual Panels} library.\\

 * to save efforts and time - as many chores as possible are moved
into the
 {\it Virtual Panels} core. This leads to the less universality and
 flexibility but at the same time makes it easier to learn and use
 {\it Virtual Panels}, so applications may be written in less time.\\

 * to save money - hardware demands are modest and most economical.\\

This guide describes only public data members and public member
functions
(we call them methods). Other details are available from header files.

\subsection*{1.3. Objects of {\it Virtual Panels}}

{\it Virtual Panels} style application looks like a front panel of
an instrument with
various kinds of indicators, graphics or alphanumerical displays,
buttons. It is an imitation of data presentation and instrument control
environment experimenter has got used to. Object-oriented approach
seems to be very natural for such a task where well defined objects have
to be performed by software means. And the use of this approach
dramatically accelerates and simplifies writing of an application as
well as {\it Virtual Panels} development itself.

\pagebreak
{\it Virtual Panels} classes (as objects are called in C++) imitate
various objects
of instrument's panel. They are divided into two groups. The first
group includes controlling objects - buttons and menus and we call them
Controls. The second group we named simply Objects and it embraces
objects that perform input-output - LEDs,  alphanumerical Indicators,
Graphs, Input Boxes ({\it Virtual Panels}  style  scanf()),
alphanumerical displays (we call them Outboxes)
and Boards (they can be used to imitate panels). Objects can be
FIXED on the screen, PERM (that means permanent and they can be dragged)
or POPUP (they appear on the screen when they are needed).
\subsection*{1.4. How {\it Virtual Panels} application works}
{\it Virtual Panels} style program consists of declarations of
objects' instances and
 procedures attached to Controls and activated when a button is
"pushed" or menu item is chosen. Buttons as well as menus are linked
in groups and allow nesting.

As you run application {\it Virtual Panels} core initializes control
subsystem,
initializes all objects in main() function you have declared, and then
program enters in the {\it Virtual Panels} loop. We call it Main Loop.
Another loop
also may be descended from the Main Loop as button- or menu-attached
procedure is called. Loop function drives button and menu subsystems,
drags objects on the screen, hides or pops them, performs memory
management and so on. All these chores are performed by {\it Virtual
Panels} core and
all you need is to call bsButSys.Loop(Backgr). Here bsButSys is the
current button system class and Backgr is a procedure which will be
executed while {\it Virtual Panels} is polling console. As you press ESC
on the
keyboard Loop quits and if you have no further intentions you can save
{\it Virtual Panels} configuration calling object::SaveCnfg("CnfFileName")
in file
CnfFileName and exit from the program.
\subsection*{1.5 Hardware notes}
{\it Virtual Panels} application supports any video card supported by
BGI.
{\it Virtual Panels}
core senses video card type during initialization and provides run-time
scale adjusting depending on the graphics mode's aspect ratio. So the
same application runs with different video cards without recompiling.
But using BGI fonts puts some limitations, because the sizes of some
objects on the screen depends on the sizes of fonts used for the texts
on these objects and that sizes cannot be adjusted. Practical use of
{\it Virtual Panels} shows that the simultaneous use of the application
with such a
difference in the aspect ratios as between VGA and EGA high resolution
modes is not a problem. This issue will be discussed later in
section 5. When you write application for true (three color) white
and black modes you have to redefine all colors so that all the details
were visible on the screen. And if you use default colors redefinition
must be done in {\it Virtual Panels} head files too.

Since {\it Virtual Panels} uses the run-time loading BGI fonts you must
have the
necessary fonts on the disk as well as a BGI graphics driver if it
wasn't linked in linking time. In this case hard disk is preferable.
Otherwise application will be slowed down dramatically because of the
constant reloading of the fonts.

\section*{2. Basics of {\it Virtual Panels}}

\subsection*{2.1 Genealogy}

Class hierarchy diagram for {\it Virtual Panels} is shown in Fig.1.
As usual the
arrows point towards the base class. As you can see there is generous
use of multiple inheritance. User accessible classes are drawn in
boldface. Friend relations are designated by (f). In this case the
arrows point towards the classes whose friends the friend classes are.

\pagebreak
\vspace{0.4cm}

\begin{picture}(0,0)
\unitlength 1.0cm
\put(0,0){\special{em:graph oktay.msp}}
\end{picture}

\vspace{10cm}

Figure 1.  Class hierarchy of {\it Virtual Panels}.


\subsection*{2.2 Base classes}

Base classes take in the most common features of the Objects.\\

 * plaque - this class defines the design of the frame of the Objects
 and the buttons. Menus have there own design and are not affected by
 plaque. There is basic structure that defines the colors of the
 plaque:

 {\footnotesize\begin{verbatim}
 struct plaquecolors { COLORS surface , shadow , ltnd; };
 \end{verbatim}}

 Here shadow is the color of the right and the lower edges of the
 plaque and lthd is the color of the lightened left and upper edges.
 By default {\it Virtual Panels} sets up the next plaque colors:

{\footnotesize\begin{verbatim}
 const plaquecolors plaquecoldflt = { LIGHTGRAY, DARKGRAY, WHITE };
\end{verbatim}}

 * display - inherits from the plaque the design of the frame.
 In addition it holds the size of the screen and performs cls() -
 clear screen operation. The display class is necessarily inherited by
 any Object that performs input or output on the screen.\\

 * object  - comprises all common properties of Objects that make them
 behave as a whole. These include title, size, type, status of the
 Object. All chores of dragging, deleting, redrawing of Objects on the
 screen, all necessary for this pointers and the memory management, all
 are in the object class. So any of Objects must inherit this base
 class.\\

 * tabstop - allows to organize ring of Objects and button groups for
 panels and dialog boxes. You can move from one tabstop Object or
 button group to another striking the TAB key on the keyboard or the
 Shift-TAB if you want to move in reverse order. In {\it Virtual Panels}
 only two
 classes are derived from tabstop class: butgrp (sect. 3.3) and
 TSInbox (sect. 4.7). You can add tabstop features to any Object by
 inheriting tabstop class and defining two virtual functions:\\

{\bf\raggedright
 virtual void Activate(void);\\
 virtual void Deactivate(void);\\}

 These methods provide procedures for entering to and exiting from the
 tabstop Object and are called by {\it Virtual Panels} core. By writing
this methods
 you define what Object does as a tabstop Object. Below is how these
 methods look for TSInbox class:\\

{\footnotesize\begin{verbatim}
 template <class T>
 void TSInbox<T>::Activate(void)
{
 cls();
 Printf(1,printfmt,*variable); // print the current value of variable
int ch=getch(); cls(); ungetch(ch); // clear it out
 switch ( Scanf(scanfmt,variable) ){
      case  0:
               msg = MSG_PREVTABSTOP;   // Shift-Tab
               goto process;
      case  9:                          // Tab
      case 13:
               msg = MSG_NEXTTABSTOP;   // Enter
               goto process;
      case 27:
               msg = MSG_EXIT;          // ESC
      process: butsystem::SendMessage( msg );
               if ( proc!=NULL ) // process the variable ?
                     *variable = proc( *variable );
               break;
      case -1: beep;            // Format error
      }
}
 virtual void Deactivate(void)
       { Refresh(); } // print the current value of variable
\end{verbatim}}


\subsection*{2.3 Versatile sizes}

As has been mentioned earlier {\it Virtual Panels} applications support
video cards
with various aspect ratios. As a standard we chose VGA and you must use
in all declarations the sizes in VGA high resolution mode pixels
(640x480). These standard sizes we call VGA sizes. Every VGA size is
converted by {\it Virtual Panels} core into what we call Versatile size
using current
aspect ratio so that the button's and the Object's shapes remained
unchanged when resolution other than 640x480 is current. We use for VGA
sizes notations with single x and y and for Versatile sizes notations
with double x and y.\\

 Example: x0, y0 are initial coordinates in VGA pixels and xx0, yy0 -
 in Versatile pixels.\\

You can use functions xx\_\_x(int), yy\_\_y(int) to convert VGA sizes
into
Versatile sizes and x\_\_xx(int), y\_\_yy(int) for the opposite
operation.\\

 Example: xx0 = xx\_\_x(x0); y0 = y\_\_yy(yy0);

\subsection*{2.4 Global variables and functions}

There are some global variables that may be useful for the user:\\

{\raggedright
{\bf int maxx,maxy;}   // Maximum size of the screen in VGA pixels\\
{\bf int maxxx,maxyy;} //     the same in the versatile pixels}

Screen maximum size is determined during initialization. It is not
recomended to modify these variables.\\

{\raggedright
{\bf  int x0s,y0s,xmaxs,ymaxs;}     // Size and location of the Dragging
area\\
{\bf  int xx0s,yy0s,xxmaxs,yymaxs;} //       the same in the versatile
pixels}\\

 * Dragging area - is the rectangular area on the screen where Objects
 can be moved. All PERManent Objects must reside completely inside this
 area.While dragging they are not able to cross the boundaries of this
 area.\\

Dragging area variables are set during initialization of {\it Virtual Panels}, but
you can change them. There are four functions doing this for you:

{\bf\raggedright
 void SetDragAreaX0( int x0);\\
 void SetDragAreaY0( int y0);\\
 void SetDragAreaXmax( int xmax);\\
 void SetDragAreaYmax( int ymax);}\\

Other four functions convert versatile sizes to VGA sizes and vice
versa:\\
 VGA to versatile:
{\bf int xx\_\_x(int x); int yy\_\_y(int y);}\\
versatile to VGA:
{\bf int x\_\_xx(int x); int y\_\_yy(int y);}



\subsection*{2.5 Types of Objects}

The type of the Object is set by the parameters of its constructor.
There are two parameters that control the {\it type} of the Object.
First is called simply type and can assume the next three values:\\

 * FIXED - the Object of this type is fixed on the screen and its
 behavior resembles that of a real object on the instrument's panel. It
 cannot be removed, dragged and always is on the screen. Use that kind
 of Objects for displaying the most important data on the screen that
 you need to see all the time. FIXED Objects must not appear inside the
 Dragging area because they are not repainted by {\it Virtual Panels}
 core when the Dragging area is corrupted.\\

 * PERM - is permanently seen on the screen, the overlapping type
 of Objects. It can be moved inside the Dragging area or even removed
 from the screen. PERM Object can appear only inside the Dragging area.
 Otherwise the screen outside the Dragging area may be corrupted. PERM
 Objects are useful for displaying information that is not necessarily
 to be always on the screen. You can remove it when it is not in need
 and then recover it in the same place when you need it. You can move
 it to the convenient place in the Dragging area at any moment.\\

 * POPUP - this type is similar to PERM type. The main difference is
 that {\it Virtual Panels} saves the underlying image when painting
 the POPUP Object
 and restores that image after removing the POPUP Object. On the one
 hand this consumes the memory, but on the other hand doesn't corrupt
 the screen and the POPUP Object unlike the PERM Object may reside
 anywhere on the screen. But nevertheless you can drag POPUP Object
 only towards or inside the Dragging area. This type is useful when you
 want only to have a peek at the information displayed by Object. It is
 useful for displaying messages, input boxes or organizing the
 ancillary panel with its own button system. This allows you to avoid
 unnecessary cluttering of the screen with Objects and buttons.\\

The second parameter is called a {\it frame} and takes two values:\\

 * UNFRAMED - when you set this value the Object has no frame around
the display, though the title and other visual attributes remain.\\

 * FRAMED - is default value and has an opposite effect.\\

The reason of defining Objects as UNFRAMED is rather esthetic. The
FIXED Objects on the panels, e.g. Indicators, look more attractive
without frames. In any case it is your choice to define Object with a
frame or without it. If you don't define Object UNFRAMED during
declaration  it is FRAMED by default.


\subsection*{2.6 Paint, button and menu procedures}

 ** All these procedures must be declared as {\bf void far Proc(void)}.\\

 * Paint procedure - is necessary for {\it Virtual Panels}
 core to repaint the PERM
 Object on the screen when it is necessary (usually after dragging the
 Object). You have to supply such a procedure for every PERM Object.
 The FIXED and POPUP Objects don't need such procedure.\\

 * Button procedure - is the procedure attached to the button. It is
 called at the every instance of pushing the corresponding button.\\

 * Menu procedure - is similar to button procedure but is called when
 the corresponding menu item is chosen.\\

We use the next prefix notation: pp  - for paint procedure, bp - for
button procedure and mp - for menu procedure.\\

 Example 2.6.1:

{\footnotesize\begin{verbatim}
 void far ppFourier(void) // Paint procedure for PERM Graph grFourier
  {
  grFourier->Paint();                     // paint Graph object
  grFourier->ShowCurve( NumPoints, XReal);// then output array on it
  }

 void far bpFourier(void)
 {
  ppFourier();     // paint grFourier over other objects on the screen
  grFourier->MkActive();// make grFourier available for dragging or
                                                  // removing
  RealFFT(....)                                   // perform FFT
  grFourier->ShowCurve( NumPoints, XReal, WHITE); // now demonstrate
  grFourier->ShowCurve( NumPoints, XImag, RED);   // Fourier spectrum
 }
\end{verbatim}}

As you see paint, button and menu procedures use pointers to classes,
because classes usually are declared in main() or other button
procedures.


\subsection*{2.7 Special procedures}

There are two special procedure that you can use for special purposes:\\

 * procDummy() - it is defined as void far procDummy(void) {}. So it
 does nothing and can be used as dummy parameter when calling
 constructors, e.g. instead of pointer to the paint procedure when you
 declare FIXED or POPUP Object, or instead of the background procedure in
 {\it Virtual Panels} loop calling bsName.Loop(procDummy).\\

 * procNULL() - it may be used instead of procDummy() when you want to
 be aware of improper call of the user-defined procedure. It makes
 error exit with error message {\it procNULL : Illegal object proc call}.


\subsection*{2.8 Macros}

There are several macro definitions in {\it Virtual Panels} header files
that can be used by the user.\\

{\bf SPACING} - it is the constant that defines the interval between rows of
text. It is a standard interval for {\it Virtual Panels} text output.\\

{\bf ON} (=1), {\bf OFF (=0)} - these constants may be used to make
the program more readable.\\

{\bf maxviewport} (= setviewport(0,0,maxxx,maxyy,CLIP\_ON) ) - macro function.
sets the current viewport to maximum  size (the whole screen).\\

{\bf beep} - macro function. Produces warning sound.


\subsection*{2.9 How to start {\it Virtual Panels}}

The first thing you have to do before using {\it Virtual Panels} features
in your program is to initialize {\it Virtual Panels} core. This must be done
in main() before the first declaration of any of {\it Virtual Panels}
classes. There are two ways of doing this. The first is calling subsequently
the next two functions:\\

{\bf\raggedright
 void InitGraphMode( int grdrv=0, char *bgipath="..$\backslash$ $\backslash$bgi");}

This function initializes the graphics system by loading a graphics
driver from disk ( or validating a registered driver) then putting
the system into graphics mode. If grdrv = EGAVGA (or 1)  then
egavga.bgi graphics driver will be linked into executable file during
linking time. By default this option is discarded and graphics driver
is chosen automatically. Then you have define by bgipath the path to
the directory where BGI graphics drivers resides.\\

{\bf\raggedright
 void InitVirtualPanels(int x0s=0, int y0s=0, int xmaxs=0, int ymaxs=0,\\
\hspace{2cm}     int fillcolor=MAGENTA, int fillptrn=CLOSE\_DOT\_FILL);}

This function initializes {\it Virtual Panels} and fills The Dragging area
with default or customized color and filling pattern, defined by fillcolor
and  fillptrn. The x0s, y0s, xmaxs and ymaxs parameters define the
Dragging area. If xmaxs or ymaxs are set to 0 then correspondingly
xmaxs or ymaxs are set to the maximum possible value. The default is that
the Dragging area occupies the whole screen.\\

The second way of initializing is shorter, you call only one function:

{\bf\raggedright
 void InitAndCopyright(\\
\hspace{2cm}  char *copyright,\\
\hspace{2cm}            int fillcolor=MAGENTA, int fillptrn=CLOSE\_DOT\_FILL,\\
\hspace{2cm}            int grdrv=0, char *bgipath=".. $\backslash$ $\backslash$bgi");\\}

The copyright is the title that will be put on the bar on the top of
the screen. Other parameters are the same as for InitGraphMode and
InitVirtualPanels functions. The Dragging area is set so that it occupies all
the screen except the bar with the title on the top of the screen. Later you
can redefine its size by modifying x0s, y0s, xmaxs, ymaxs and xx0s,
yy0s, xxmaxs, yymaxs global variables.\\

 * ATTENTION. If you choose default option for grdrv ( that means: don't
 include EGAVGA.BGI graphics driver in EXE file) and you have not included
 object code of EGAVGA.BGI into your project or GRAPHICS.LIB, you will
 receive linker error message that \_EGAVGA\_driver\_far is undefined. To
 avoid this include the following line in your main module before main():

 {\footnotesize\begin{verbatim}
  int far EGAVGA_driver_far[1];
\end{verbatim}}

\subsection*{2.10 How to quit {\it Virtual Panels}}

To quit {\it Virtual Panels} you call function\\

{\bf\raggedright
 void QuitVirtualPanels(void);}

This function restores palette, CRT mode and other parameters had been
changed when {\it Virtual Panels} was initialized.

\pagebreak
\section*{3. Controls}

Controls are {\it Virtual Panels} classes dedicated to manipulate Objects and control
the flow of the program. There are two kinds of Controls - the buttons
and the menus - which do the same thing - call attached user defined
procedures (section 2.6). The difference is in their organization.
Buttons are linked in button groups. Button groups in their turn are
linked in what we call button system. The menu structure is declared in
the special menu system function. Menu system function must be
registered with the current button system in the program.\\

 * State of the Control - the private data member keeps the state of
 button or menu item. There can be four states:

  CRL\_DISABLED - Control is disabled. It means that it is grayed on the
  screen and has no effect.

  CRL\_HLDISABLED - Control is disabled but currently highlighted, i.e.
  chosen, but pushing Enter on the keyboard does not lead to any
  effect.

  CRL\_ACTIVE - Control is enabled and highlighted and pushing Enter
  calls button or menu procedure.

  CRL\_ENABLED - Control is enabled but not highlighted.


\subsection*{3.1 Button}

Button is a plaque with a title on it, and if you click it, it calls
a user defined function. We call this function a button procedure or an
attached procedure. The button class inherits only plaque base class.\\\\
Constructor:\\

{\bf\raggedright
 button (\\
\hspace{2cm}    char *title,                   {\sf     // text on the button}\\
\hspace{2cm}      char ascii0, char ascii1,    {\sf  // kbd short-cuts}\\
\hspace{2cm}      void (far *proc)(void),      {\sf     // button procedure}\\
\hspace{6cm}                   {\sf     //---------- Hereafter are defaults}\\
\hspace{2cm}      int textfont=0,int txsize=1, {\sf     // font style and size of text}\\
\hspace{2cm}      buttoncolors buttextcnfg=buttextdflt, {\sf //colors of text}\\
\hspace{2cm}      plaquecolors butcol=butcoldflt);     {\sf  //colors of button}
}

There are four obligatory parameters:\\
title - is the text to be put on the button, ascii0 and ascii1 - are
short-cuts for pushing button from keyboard. How these parameters can
be used is clear from the example 3.1.1. The proc is the user defined
button procedure (see section 2.6).

You may omit other parameters . Type of title's font is by default BGI
8x8 bit mapped DEFAULT\_FONT. In many cases it is more appropriate to
use stroked SMALL\_FONT. Of course you can use any BGI fonts. The last
two parameters are color structures (see section 3.5).\\\\
{\large Data members:\\}

{\bf\raggedright
 int x0, y0, xmax, ymax;\\
 int xx0, yy0, xxmax, yymax;\\
}

This data members are set automatically by constructor. They define
rectangular space on the screen occupied by button. You can only read
them, not modify. That sort of data members is useful when you are
disposing objects on the screen.\\

{\bf\raggedright
 int status;\\}

Private data member. May be CRL\_ACTIVE, CRL\_ENABLED, CRL\_DISABLED or CRL\_HLDISABLED.
This data member defines the state of the button.\\\\
{\large Methods:\\}

{\bf\raggedright
 virtual void Paint(void);}

Paints individual button.\\

{\bf\raggedright
 void Enable(void);\\
 void Disable(void);\\}

Enables or disables the button (makes status = CRL\_ENABLED or status =
CRL\_DISABLED). After the use of this methods it is recomended to
repaint the button - call Paint() method.\\

{\bf\raggedright
 int GetStatus(void);\\}

Returns current status of the button, that can be CRL\_ACTIVE,
CRL\_ENABLED, CRL\_DISABLED or CRL\_HLDISABLED.


\subsection*{3.2 Buttons with indication}

The indbutton class inherits the button class and the LED class.
It is simply a button with a LED indicator. It is useful when the button
is used as a toggle or a switch and it is necessary to indicate the state
of the system to which the button is attached. It also can be used as a
check box in dialogue panels.\\\\
Constructor:\\

{\bf\raggedright
 indbutton(\\
\hspace{2cm}    char *title, char ascii0, char ascii1,\\
\hspace{2cm}    void (far *proc)(void),\\
\hspace{2cm}    int indradius=4,             {\sf  // radius of indicator}\\
\hspace{2cm}    int textfont=0,int textsize=1,{\sf // font style and size of text}\\
\hspace{2cm}    LEDcolors indcol=redLED,            {\sf  //colors of LED}\\
\hspace{2cm}    buttoncolors buttextcnfg=buttextdflt,{\sf //colors of textl}\\
\hspace{2cm}    plaquecolors butcol=butcoldflt);     {\sf //colors of button}
}

The new here (in comparison with the button) is that you can change the
radius or color of the LED indicator overriding the default parameters. By
default the indicator is red. In essence the indbutton is the sum of button
and LED classes and doesn't add any new data members or methods except
the Paint() method which is virtual method specific for each class.\\\\
{\large Data members:}\\

{\bf\raggedright
 int on;\\}

Status of LED. Is 0 if LED is off and 1 if LED is lighted up. Inherited
from the LED class.\\\\
{\large Methods:}\\

There are three methods inherited from the LED class:\\
{\bf\raggedright
 void On(void);\\
 void Off(void);\\}
Switches indicator on or off.\\
{\bf\raggedright
 void Invert(void);\\}
Changes the state of the indicator to the opposite.


\subsection*{3.3 Button Groups}

It is handy for the user when buttons are linked in groups in accordance
with their functions. The butgrp is a tabstop object - it is derived
from the tabstop class. Therefore you can move from one button group to
another striking TAB key on the keyboard or Shift-TAB if you want to
move in reverse order. The button group concept makes a crowd of
buttons more organized and the access to the individual button easier.\\\\
Constructor:\\

{\bf\raggedright
 butgrp (\\
\hspace{2cm} int x0, int y0,     {\sf // the starting point}\\
\hspace{2cm}      int xlen, int ylen,    {\sf // size of buttons}\\
\hspace{2cm}      int direction = HORIZ, {\sf // The direction of button's lining up}\\
\hspace{6cm}                             {\sf // May be VERT or HORIZ.}\\
\hspace{2cm}      int distance = 0 );    {\sf // Gap between buttons. In VGA pixels.}}

The xlen, ylen are horizontal and vertical sizes of buttons in that
group. The x0, y0 is the starting point - defines the upper left corner
of the first button of button group on the screen.

By default buttons in group visually are lined up in the horizontal
direction. If you want to organize them vertically pass VERT constant
for direction parameter. Distance between buttons is zero by default.
This is the most economical use of the space on the screen.\\\\\\
{\large Data members:}\\

None accessible to the user. There are two private static data members x0
and y0 which define the location of the next button in the group. When
you declare a button, its constructor increases these variables in
accordance with xlen or ylen and direction and distance parameters of
butgrp costructor.\\\\
{\large Methods:}\\

{\bf\raggedright
 virtual void Paint(void);\\}

Paints all buttons of the group on the screen. In effect this method
calls subsequently individual Paint() method of each button.\\\\
{\bf Shifts}. Allow you to customize disposition of buttons on the screen. By
default buttons are simply lining up horizontally or vertically. The
Shift methods modify private static data members x0 and y0, changing
position of the button to be declared next:\\

{\bf
\raggedright
 void ShiftX( int x);\\
 void ShiftY( int y);\\}

Add x to x0 and y to y0\\

{\bf\raggedright
 void ShiftToX( int x);\\
 void ShiftToY( int y);\\}

Make x0 = x and y0 = y.\\

To switch between button groups use butsystem method \mbox{NextTabStop()}\\
and \mbox{PrevTabStop()}.\\\\
Example 3.1.1:

{\footnotesize\begin{verbatim}
#define butFONT         SMALL_FONT
#define butFONT_SIZE    4

butgrp bgCamacCtrl( CamacCtrl_but_x0, CamacCtrl_but_y0,
             /* size of button:*/ 60,18, VERT, 2 /* gap */ );

 button butEnterAC("AC", 'A','a', bpEnterAC, butFONT, butFONT_SIZE);
 button butEnterDC("DC", 'D','d', bpEnterDC, butFONT, butFONT_SIZE);
 indbutton ibutHeater("Heater", 'H','h', bpHeater,
                      4 /* radius of ind.*/,butFONT, butFONT_SIZE);
 button butGain("Gain", 'G','g', bpGain, butFONT, butFONT_SIZE);

butgrp bgHorizButtons( 3, maxy-25,      // starting point
                       70, 20);         // size of button
 button butQuit( "Quit", 'Q','q', bpQuit, 0,1, quittexcol, quitbutcol);
 button butHelp( "Help", 'H','h', bpHelp);
  bgHorizButtons.ShiftX(10);
 button but Tdependence( "Tdep", 0,67 /* F9 */, bpTdep);
 button butTdepGraph( "Graph", 'G','g', bpTdepGraph);

bgCamacCtrl.Paint();
bgHorizButtons.Paint();
\end{verbatim}}

Here are declared two button groups - bgCamacCtrl and bgHorizButtons.
Camac control buttons are smaller and are lined up vertically with gaps
between buttons equal to two VGA pixels. The texts on these buttons are
smaller than on the buttons of bgHorizButtons group. All colors are
default button colors except of the "Quit" button that is red with
white text (these colors are also standard for {\it Virtual Panels},
see section 3.5). The peculiarity of bgCamacCtrl group is the ibutHeater button
with LED indicator. The bpHeater switches heater on or off while
indicator shows its state. In HorizButtons group we used ShiftX method
to make a gap between general purpose buttons and buttons devoted to T-
dependence measurement.

You can click button choosing it by arrow keys and pushing Enter, or
striking the shortcut letter on the keyboard. Any two ASCII codes or
one extended ASCII code may be used as a short-cuts. Usually it is
preferable to define short-cuts as the upper-case and the lower-case
letters emphasized (in a upper-case) on the title of the button.
Another way is to put ascii0=0 and then ascii1 defines extended ASCII
code. In this case you must be sure that the extended ASCII code
doesn't clash with keys reserved by {\it Virtual Panels} (see Appendix B). In the
example 3.1.1 T-dependence measurement is started off by pushing F9
key.\\

 ** Short-cut ASCII codes must be unique within the button group.\\

 ** Declaration of the button group makes it current. Buttons are
 linked to the current button group as they are declared in the run-
 time order, until a new button group is declared.


\subsection*{3.4 Button system}

All classes derived from the tabstop base class link together in order of
declaration and the whole construction we call the button system. The
button system may be considered as a ring of button groups and tabstop
Objects. Button groups are itself the rings of buttons. The tabstop
Objects start linking to each other as the butsystem class is declared.\\

 ** Button groups must be declared after the declaration of the button
 system. The good style of programming is to declare the button system
 first in the procedure.\\\\
Constructor:\\

{\bf\raggedright
 butsystem(int master = 0); {\sf // Is not master by default}}

The button system has access to the Stack of the Objects (sect.4) only
if master=MASTER, i.e. non-zero. Otherwise the button system will only
control tabstop Objects and button groups. Usually only the button
system in the main() is declared as MASTER.\\\\
{\large Data members:}\\

{\bf\raggedright
 unsigned int   ConStatus;{\sf // status of kbd and mouse}\\
 unsigned char  key0;     {\sf // ascii codes of last keystroke}\\
 unsigned char  key1;}

These data members can be used by the Background procedure. The Loop
method sets them when actions occurred on the console. The key0 keeps
ASCII code of the key stricken last. If it is zero then the key1 keeps
extended ASCII code. Using ConStatus you can determine if the key was hit
just now. This flag is cleared during the next polling of console. If
(bsMain.ConStatus \& KBD\_HIT) == 1 the key was hit.\\\\
{\large Methods:}\\

{\bf\raggedright
 int RegisterMenu(int (far *MenuSysFunc)(void));}

Registers the menu system function with the button system. Returns TRUE
if registration succeeded or FALSE if failed.\\

{\bf\raggedright
 void NextTabStop(void);\\
 void PrevTabStop(void);}

To make the next or the previous tabstop object active. Usually this
can be done from console striking Tab or Shift-Tab keys. These methods
allow you to do this from the program. There may be problems using this
functions when there are tabstop Object which are waiting input from
the keyboard when activated (for example the TSInbox Object). To skip
such Object you have to provide the input for this Object. For example
if the next Object is the TSInbox Object you can write the following
code:

{\footnotesize\begin{verbatim}
ungetch(13);            // provide CR for the TSInbox Object
bsMain.NextTabStop();  // now the TSInbox Object get CR and
                  // program returns from the Activate method
\end{verbatim}}

{\bf\raggedright
 void NextButton(void);\\
 void PrevButton(void);}

To make the next or the previous button in active group active. Usually
this can be done from console by arrow keys. These methods allow you to
do this from the program.\\

{\bf\raggedright
 void Loop(void (far *BkgrndProc)(void));}

Puts button system into effect. Before calling this function you should
be certain that you have declared all the objects. This method
organizes what we call {\it Virtual Panels} Loop, which polls the console
and, when the key is pushed or mouse is clicked, takes the necessary actions.
Those include dragging the object on the screen, pushing the button and
calling the button procedure, activation of the menu system and so on.
After each polling Loop calls the user supplied background function
void far BkgrndProc(). This function takes the control on the program
and the polling resumes when the program returns from BkgrndProc(). In
section 5 we offer the style of writing BkgrndProc(). Of course you
can regard BkgrndProc() as a foreground routine and the Loop as a
background routine, which takes control under your permission. This
allows you to perform the data processing and presentation, while
controlling the flow of program from console. Of course BkgrndProc()
hardly can be used for the real time data acquisition. The use of the
interrupt handlers and the mail boxes is the best way to do this.\\

{\bf\raggedright
 void SendMessage(int messg);}

Sends the message messg to the {\it Virtual Panels} Loop. In this version Loop method
responds only to messages:

MSG\_EXIT\\
 has the same effect as striking ESC on the keyboard. Loop breaks and
 the next statement after the Loop in the program is executed.

MSG\_NEXTTABSTOP, MSG\_PREVTABSTOP\\
 have the same effect as striking TAB or Shift-TAB on the keyboard.\\\\
Example 3.1.2. :\\

{\footnotesize\begin{verbatim}
//------------------  CONFIRM ----------------------
//----- returns FALSE if 'No' button was pressed,
//-----         TRUE     'Yes'
int resp=0;     // Status register 1- Yes,  0 - No. Default is No
butsystem *pbsYN;

void far bpYes(void)
        { resp=1; pbsYN->SendMessage(MSG_EXIT);} // exit Loop
void far bpNo(void)
        { resp=0; pbsYN->SendMessage(MSG_EXIT);} // exit Loop

int _Cdecl Confirm(char *mess)
{
pbsYN = new butsystem;
Outbox Ask( maxx>>2, maxy>>2,   // coord. of LEFT-TOP corner
            POPUP, "Confirm",   // title of box
            strlen(mess)+2, 5,  // size of box
            FRAMED, procNULL,  // no paint procedure is defined
            0,1, 0,1); // title and text use raster fonts
butgrp YesNo( (Ask.xmax+Ask.x0-110)>>1, Ask.ymax-40, 50, 21, HORIZ, 10);
 button Yes("Yes",'y','Y',bpYes);
 button No("No",'n','N',bpNo);

 Ask.Paint();
 Ask.SetTextJustify( CENTER_TEXT );
 Ask.Putn("");       // skip one line
 Ask.Put( mess,1);   // and print your suggestion
 YesNo.Paint();

 pbsYN->NextButton();
 pbsYN->Loop(procDummy);        // Now wait responce
 delete pbsYN;

 Ask.Remove();  // remove box from the screen
 return resp;   // return TRUE if Yes, FALSE if No
}
\end{verbatim}}

This is an example how to organize confirmation box. When you call in
your program e.g.
{\footnotesize\begin{verbatim}
 Confirm("Save the data ?");
\end{verbatim}}
on the screen appears the box with text "Save the data ?" and two
buttons beneath: "Yes" and "No". That is the new button system which
consists of the one button group with two buttons. When you choose one
of the buttons, the new button system quits, the preceding one restores
and the box disappears. You can also strike ESC key to quit the new button
system, but in this case the default value of resp will be returned.


\subsection*{3.5 Button colors}

Button colors are fixed by two color structures: plaquecolors,
inherited from the class plaque ( section 2.2 ), and\\

{\raggedright
 struct buttoncolors \{ COLORS\\
\hspace{6cm}      disabledtext,\\
\hspace{6cm}      hldisabltext, // color of highlighted disabled text\\
\hspace{6cm}      enabledtext,\\
\hspace{6cm}      activetext; \};}\\

The members of this structure correspond to the states of the button
(See sect. 3).\\

There are two pre-defined sets of colors for buttons:

{\footnotesize\begin{verbatim}
//--- Default button colors
const plaquecolors butcoldflt = { DARKGRAY, BLACK, LIGHTGRAY };
const buttoncolors
        buttextdflt = {
                                 BLACK,         // disabled
                                 LIGHTGRAY,     // disabled highlighted
                                 GREEN,         // enabled
                                 LIGHTGREEN};   // enabled highlighted

//--- Quit button colors
const plaquecolors quitbutcol={  RED, BLACK, LIGHTGRAY };
const buttoncolors quittexcol={ BLACK, DARKGRAY, LIGHTGRAY, WHITE };
\end{verbatim}}

Default colors are the colors that button will have if you haven't
decided otherwise. The example of the customized colors is the Quit
button colors - the pre-defined constants that allow to emphasize the
Quit button.


\subsection*{3.6 Menu system}

Menu system is only slightly connected with other parts of
{\it Virtual Panels}.
It is not included into the genealogy of {\it Virtual Panels}.
Moreover your can
supply your own menu system if you want. The embedding of the menu
system into the {\it Virtual Panels} application is very simple.
First you write the
function that contains your menu system. This means that when this
function is called menu is activated and takes on the control over
the program. The menu system function itself supports the keyboard and
the mouse and calls menu procedures when menu items are chosen. If you
use menu system supplied by {\it Virtual Panels} you only have to declare
the structure
of menu and call the msName.Loop(BackgrProc) in the menu system
function. You can write several menu system functions with different
menu structures. To embed the menu system into the button system you
must register the menu system before calling the button system Loop
method. To do this you call the function RegisterMenu(MenuSysFunc),
where the MenuSysFunc is the name of the far menu system function. As
the program enters into the button system Loop the menu system is
activated by pushing the Alt key on the keyboard or the right button on
the mouse. {\it Virtual Panels} menu system guide will be supplied
separately as the
text file with the {\it Virtual Panels} package.
\vskip5cm
\begin{center}
{Рукопись поступила в издательский отдел\\
26 сентября 1993 года}
\end{center}

\end{document}
